package com.wzdigit.wms.wms.service.transfer;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wzdigit.framework.Shift;
import com.wzdigit.mes.basic.api.BasicDataItemApi;
import com.wzdigit.mes.basic.api.BasicDataItemDetailApi;
import com.wzdigit.mes.basic.dto.DataItemDetailDTO;
import com.wzdigit.wms.basic.client.Pager;
import com.wzdigit.wms.basic.client.PagerInfo;
import com.wzdigit.wms.basic.client.request.transfer.SearchInvRequest;
import com.wzdigit.wms.basic.client.response.transfer.InvLocGoodsListResponse;
import com.wzdigit.wms.basic.client.response.transfer.InvLocListResponse;
import com.wzdigit.wms.basic.client.response.transfer.InvZoneListResponse;
import com.wzdigit.wms.basic.domain.inventory.Goods;
import com.wzdigit.wms.basic.domain.transfer.InvZone;
import com.wzdigit.wms.basic.enums.GoodsStatusEnum;
import com.wzdigit.wms.basic.enums.InvAttrEnum;
import com.wzdigit.wms.basic.enums.QaStatusEnum;
import com.wzdigit.wms.basic.enums.basic.LotAttrDtlEnum;
import com.wzdigit.wms.basic.mapper.core.inventory.GoodsMapper;
import com.wzdigit.wms.basic.mapper.core.inventory.InvLocMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.InvZoneMapper;
import com.wzdigit.wms.common.entity.ExcelExportConfig;
import com.wzdigit.wms.common.utils.HttpExcel;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 库区库存-服务类
 *
 * @author yangdongjie
 * @GdnService.java
 * @2021年2月24日下午3:25:03
 */
@Service
public class InvZoneService {

    @Autowired
    private InvZoneMapper invZoneMapper;

    @Autowired
    private InvLocMapper invLocMapper;
    
    @Autowired
    private GoodsMapper goodsMapper;
    
    @Reference(version = "${dubbo.consumers.basic.data.item.detail.api:1.0.0}", check = false, timeout = 300000)
	private BasicDataItemDetailApi dataItemDetailApi;
	
	@Reference(version = "${dubbo.consumers.basic.data.item.api:1.0.0}", check = false, timeout = 300000)
	private BasicDataItemApi dataItemApi;

    private static Map<String, String> InvAttrMap = InvAttrEnum.getEnumByDescription();
    private static Map<Integer, String> qaStatusMap = QaStatusEnum.getEnumByDescription();

    private static final String PONO_CODE = LotAttrDtlEnum.PO_NO.code;

    private static final String SO_NO = LotAttrDtlEnum.SO_NO.code;

    private static final String SO_ITEM = LotAttrDtlEnum.SO_ITEM.code;

    /**
     * 查询库区库存
     * 
     * @param dto
     * @param filter
     * @param pager
     * @return
     */
    public <T> PagerInfo<List<InvZoneListResponse>> searchInvZone(SearchInvRequest dto,
                                                                  String poNo, String soNo, String soItem, String filter, Pager<T> pager) {
        if(Objects.equals(InvAttrEnum.S.getCode(), dto.getInvAttr())) {
            dto.setInvAttr(null);
        }
        Page<?> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<InvZoneListResponse>> pagerInfo = new PagerInfo<List<InvZoneListResponse>>();
        List<InvZoneListResponse> list = invZoneMapper.selectAll(dto, poNo, soNo, soItem, filter);
        list.forEach(one -> {
            if (StringUtils.isNotBlank(one.getLotAttrCode())) {
                Map<String, String> map = JSON.parseObject(one.getLotAttrCode(), Map.class);
                one.setPoNo(map.get(PONO_CODE));
                one.setSoNo(map.get(SO_NO));
                one.setSoItem(map.get(SO_ITEM));
            }
        });
        pagerInfo.setItems(list);
        pagerInfo.setTotalCount(page.getTotal());
        return pagerInfo;
    }

    /**
     * 查询库位库存
     * 
     * @param dto
     * @param pager
     * @return
     */
    public <T> PagerInfo<List<InvLocListResponse>> searchInvLoc(SearchInvRequest dto, Pager<T> pager) {
        Page<?> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<InvLocListResponse>> pagerInfo = new PagerInfo<List<InvLocListResponse>>();
        List<InvLocListResponse> list = invLocMapper.selectAll(dto);
        pagerInfo.setItems(list);
        pagerInfo.setTotalCount(page.getTotal());
        return pagerInfo;
    }
    
    /**
     * 根据库位库存查找sn
     * 
     * @param dto
     * @return
     */
    public PagerInfo<List<InvLocGoodsListResponse>> searchGoodsByInvLoc(SearchInvRequest dto,Pager<?> pager) {
        dto.setVendorId(null);
        Page<InvLocGoodsListResponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        List<InvLocGoodsListResponse> datas = goodsMapper.selectByInvLoc(dto);
        PagerInfo<List<InvLocGoodsListResponse>> pagerInfo = new PagerInfo<>();
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);
        return pagerInfo;
    }
    
    /**
     * 导出库区库存
     * 
     * @param dto
     * @param filter
     * @param request
     * @param response
     * @throws Exception
     */
    public void export(SearchInvRequest dto, String poNo, String soNo, String soItem, String filter, 
    		HttpServletRequest request, HttpServletResponse response) throws Exception {
    	List<DataItemDetailDTO> ownerList = dataItemDetailApi.getDataItemDetailByCode("default_owner");
    	Map<String, String> ownerMap = ownerList.stream().collect(
    			Collectors.toMap(DataItemDetailDTO::getItemValue, DataItemDetailDTO::getItemName));

        ServletOutputStream out = null;
        XSSFWorkbook workbook = null;
        try {
        	if(Objects.equals(InvAttrEnum.S.getCode(), dto.getInvAttr())) {
        		dto.setInvAttr(null);
        	}
            List<InvZoneListResponse> datas = invZoneMapper.selectAll(dto, poNo, soNo, soItem, filter);
            datas.forEach(one -> {
            	one.setCustomerName(ownerMap.get(String.valueOf(one.getOwnerId())));
                one.setQaStatus(qaStatusMap.get(Integer.parseInt(one.getQaStatus())));
                one.setInvAttr(InvAttrMap.get(one.getInvAttr()));
                if (StringUtils.isNotBlank(one.getLotAttrCode())) {
                    Map<String, String> map = JSON.parseObject(one.getLotAttrCode(), Map.class);
                    one.setPoNo(map.get(PONO_CODE));
                    one.setSoNo(map.get(SO_NO));
                    one.setSoItem(map.get(SO_ITEM));
                }
            });

            List<ExcelExportConfig> configs = new ArrayList<>();
            configs.add(new ExcelExportConfig("仓库", "whsCode", 120));
            configs.add(new ExcelExportConfig("仓库名称", "whsName", 120));
            configs.add(new ExcelExportConfig("库区", "zoneCode", 120));
            configs.add(new ExcelExportConfig("库区名称", "zoneName", 120));
            configs.add(new ExcelExportConfig("货主", "customerName", 120));
            configs.add(new ExcelExportConfig("货品", "skuCode", 120));
            configs.add(new ExcelExportConfig("货品名称", "descCn", 300));
            configs.add(new ExcelExportConfig("组织", "factory", 120));
            configs.add(new ExcelExportConfig("供应商", "vendorName", 120));
            configs.add(new ExcelExportConfig("批次号", "lotno", 120));
            configs.add(new ExcelExportConfig("批次属性", "lotAttr", 120));
            configs.add(new ExcelExportConfig("订单号", "poNo", 120));
            configs.add(new ExcelExportConfig("销售订单号", "soNo", 120));
            configs.add(new ExcelExportConfig("销售订单行号", "soItem", 120));
            configs.add(new ExcelExportConfig("品质状态", "qaStatus", 120));
            configs.add(new ExcelExportConfig("库存数量", "qty", 120));
            configs.add(new ExcelExportConfig("可用数量", "availableQty", 120));
            configs.add(new ExcelExportConfig("冻结数量", "holdQty", 120));
            configs.add(new ExcelExportConfig("预收数量", "preInQty", 120));
            configs.add(new ExcelExportConfig("预支数量", "preOutQty", 120));

            configs.add(new ExcelExportConfig("预配数量", "preAlocQty", 120));
            configs.add(new ExcelExportConfig("分配数量", "alocQty", 120));
            configs.add(new ExcelExportConfig("单位", "unit", 120));
            configs.add(new ExcelExportConfig("库存性质", "invAttr", 120));
            configs.add(new ExcelExportConfig("备注", "comments", 120));


            workbook = HttpExcel.newListToExcel(datas, configs);
            String userAgent = request.getHeader("USER-AGENT");
            String fileName = "库区库存";
            if (userAgent.contains("Mozilla")) {
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "utf8");
            }
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;fileName=" + fileName + ".xlsx");
            response.flushBuffer();
            out = response.getOutputStream();
            workbook.write(out);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
			if(workbook != null) {
				workbook.close();
			}
        }
    }

    /**
     * 主键查询
     * 
     * @param invZoneId
     * @return
     */
    public InvZone selectByPk(Integer invZoneId) {
        InvZone invZone = invZoneMapper.selectById(invZoneId);
        return invZone;
    }
    
    /**
     * 根据googs查找对应的库区库存
     * 
     * @param goods
     * @param zoneId
     * @return
     */
    public InvZone getEffectiveInvLoc(Goods goods, Integer zoneId) {
        //创建类型的条件构造器
        QueryWrapper<InvZone> wrapper = new QueryWrapper<>();
        //ZONE_ID
        if (zoneId == null) {
            wrapper.isNull("ZONE_ID");
        } else {
            wrapper.eq("ZONE_ID", zoneId);
        }
        //WHS_ID
        if (goods.getWhsId() == null) {
            wrapper.isNull("WHS_ID");
        } else {
            wrapper.eq("WHS_ID", goods.getWhsId());
        }
        //OWNER
        if (goods.getOwner() == null) {
            wrapper.isNull("OWNER");
        } else {
            wrapper.eq("OWNER", goods.getOwner());
        }
        //SKU_ID
        if (goods.getSkuId() == null) {
            wrapper.isNull("SKU_ID");
        } else {
            wrapper.eq("SKU_ID", goods.getSkuId());
        }
        //FACTORY
        if (goods.getFactory() == null) {
            wrapper.isNull("FACTORY");
        } else {
            wrapper.eq("FACTORY", goods.getFactory());
        }
        //VENDOR_ID
        if (goods.getVendorId() == null) {
            wrapper.isNull("VENDOR_ID");
        } else {
            wrapper.eq("VENDOR_ID", goods.getVendorId());
        }
        //LOTNO
        if (goods.getLotno() == null) {
            wrapper.isNull("LOTNO");
        } else {
            wrapper.eq("LOTNO", goods.getLotno());
        }
        //INV_ATTR
        if (goods.getInvAttr() == null) {
            wrapper.isNull("INV_ATTR");
        } else {
            wrapper.eq("INV_ATTR", goods.getInvAttr());
        }
        //QA_STATUS
        if (goods.getQaStatus() == null) {
            wrapper.isNull("QA_STATUS");
        } else {
            wrapper.eq("QA_STATUS", goods.getQaStatus());
        }
        InvZone invZone = invZoneMapper.selectOne(wrapper);
        return invZone;
    }

    public List<InvZone> searchInvZoneByKey(SearchInvRequest searchInvRequest) {

        //创建类型的条件构造器
        QueryWrapper<InvZone> wrapper = new QueryWrapper<>();

//        wrapper.isNull(searchInvRequest.getZoneId() == null, "ZONE_ID");
        wrapper.eq(!(searchInvRequest.getZoneId() == null), "ZONE_ID", searchInvRequest.getZoneId());

//        wrapper.isNull(searchInvRequest.getWhsId() == null, "WHS_ID");
        wrapper.eq(!(searchInvRequest.getWhsId() == null), "WHS_ID", searchInvRequest.getWhsId());

//        wrapper.isNull(searchInvRequest.getOwnerId() == null, "OWNER");
        wrapper.eq(!(searchInvRequest.getOwnerId() == null), "OWNER", searchInvRequest.getOwnerId());

//        wrapper.isNull(searchInvRequest.getSkuId() == null, "SKU_ID");
        wrapper.eq(!(searchInvRequest.getSkuId() == null), "SKU_ID", searchInvRequest.getSkuId());

//        wrapper.isNull(searchInvRequest.getFactory() == null, "FACTORY");
        wrapper.eq(!(searchInvRequest.getFactory() == null), "FACTORY", searchInvRequest.getFactory());

//        wrapper.isNull(searchInvRequest.getVendorId() == null, "VENDOR_ID");
        wrapper.eq(!(searchInvRequest.getVendorId() == null), "VENDOR_ID", searchInvRequest.getVendorId());

//        wrapper.isNull(searchInvRequest.getLotno() == null, "LOTNO");
        wrapper.eq(!(searchInvRequest.getLotno() == null), "LOTNO", searchInvRequest.getLotno());

//        wrapper.isNull(searchInvRequest.getInvAttr() == null, "INV_ATTR");
        wrapper.eq(!(searchInvRequest.getInvAttr() == null), "INV_ATTR", searchInvRequest.getInvAttr());

//        wrapper.isNull(searchInvRequest.getQaStatus() == null, "QA_STATUS");
        wrapper.eq(!(searchInvRequest.getQaStatus() == null), "QA_STATUS", searchInvRequest.getQaStatus());

        List<InvZone> invZoneList = invZoneMapper.selectList(wrapper);
        return invZoneList;
    }

    //库存报表主档【新】
    public <T> PagerInfo<List<InvZoneListResponse>> searchInvLocNew(SearchInvRequest dto,
                                                                  String poNo, String soNo, String soItem, String whsType, String filter, Pager<T> pager) {
        if(Objects.equals(InvAttrEnum.S.getCode(), dto.getInvAttr())) {
            dto.setInvAttr(null);
        }
        if (dto!=null){
            if (dto.getGoodsSn()!=null){
                Goods goods = goodsMapper.selectOne(new QueryWrapper<Goods>().
                        eq("GOODS_SN", dto.getGoodsSn()));
                if (goods==null){
                    Shift.fatal("条码["+dto.getGoodsSn()+"]未在库存中");
                }
                this.setInvLocSearch(dto,goods);
            }
        }
        if(whsType==null || whsType==""){
            whsType = "3";
        }
        Page<?> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<InvZoneListResponse>> pagerInfo = new PagerInfo<List<InvZoneListResponse>>();
        List<InvZoneListResponse> list = invZoneMapper.selectAllNew(dto, poNo, soNo, soItem, whsType, filter);
        list.forEach(one -> {
            if (StringUtils.isNotBlank(one.getLotAttrCode())) {
                Map<String, String> map = JSON.parseObject(one.getLotAttrCode(), Map.class);
                one.setPoNo(map.get(PONO_CODE));
                one.setSoNo(map.get(SO_NO));
                one.setSoItem(map.get(SO_ITEM));
            }
        });
        pagerInfo.setItems(list);
        pagerInfo.setTotalCount(page.getTotal());
        return pagerInfo;
    }


    //导出库存报表主档【新】
    public void exportNew(SearchInvRequest dto, String poNo, String soNo, String soItem, String whsType, String filter,
                          HttpServletRequest request, HttpServletResponse response) throws Exception {
        List<DataItemDetailDTO> ownerList = dataItemDetailApi.getDataItemDetailByCode("default_owner");
        Map<String, String> ownerMap = ownerList.stream().collect(
                Collectors.toMap(DataItemDetailDTO::getItemValue, DataItemDetailDTO::getItemName));

        ServletOutputStream out = null;
        XSSFWorkbook workbook = null;
        try {
            if(Objects.equals(InvAttrEnum.S.getCode(), dto.getInvAttr())) {
                dto.setInvAttr(null);
            }
            if (dto!=null){
                if (dto.getGoodsSn()!=null){
                    Goods goods = goodsMapper.selectOne(new QueryWrapper<Goods>().
                            eq("GOODS_SN", dto.getGoodsSn()));
                    if (goods==null){
                        Shift.fatal("条码["+dto.getGoodsSn()+"]未在库存中");
                    }
                    this.setInvLocSearch(dto,goods);
                }
            }
            if(whsType==null || whsType==""){
                whsType = "1";
            }
            List<InvZoneListResponse> datas = invZoneMapper.selectAllNew(dto, poNo, soNo, soItem, whsType, filter);
            datas.forEach(one -> {
                one.setCustomerName(ownerMap.get(String.valueOf(one.getOwnerId())));
                one.setQaStatus(qaStatusMap.get(Integer.parseInt(one.getQaStatus())));
                one.setInvAttr(InvAttrMap.get(one.getInvAttr()));
                if (StringUtils.isNotBlank(one.getLotAttrCode())) {
                    Map<String, String> map = JSON.parseObject(one.getLotAttrCode(), Map.class);
                    one.setPoNo(map.get(PONO_CODE));
                    one.setSoNo(map.get(SO_NO));
                    one.setSoItem(map.get(SO_ITEM));
                }
            });

            List<ExcelExportConfig> configs = new ArrayList<>();
            configs.add(new ExcelExportConfig("仓库", "whsCode", 120));
            configs.add(new ExcelExportConfig("仓库名称", "whsName", 120));
            configs.add(new ExcelExportConfig("库区", "zoneCode", 120));
            configs.add(new ExcelExportConfig("库区名称", "zoneName", 120));
            configs.add(new ExcelExportConfig("库位", "locCode", 120));
            configs.add(new ExcelExportConfig("订单号", "poNo", 120));
            configs.add(new ExcelExportConfig("货品", "skuCode", 120));
            configs.add(new ExcelExportConfig("货品名称", "descCn", 300));
            configs.add(new ExcelExportConfig("品质状态", "qaStatus", 120));
            configs.add(new ExcelExportConfig("库存数量", "qty", 120));
            configs.add(new ExcelExportConfig("可用数量", "availableQty", 120));
            configs.add(new ExcelExportConfig("冻结数量", "holdQty", 120));
            configs.add(new ExcelExportConfig("预收数量", "preInQty", 120));
            configs.add(new ExcelExportConfig("预支数量", "preOutQty", 120));
            configs.add(new ExcelExportConfig("预配数量", "preAlocQty", 120));
            configs.add(new ExcelExportConfig("分配数量", "alocQty", 120));

            configs.add(new ExcelExportConfig("组织", "factory", 120));
            configs.add(new ExcelExportConfig("供应商", "vendorName", 120));
            configs.add(new ExcelExportConfig("批次号", "lotno", 120));
            configs.add(new ExcelExportConfig("批次属性", "lotAttr", 120));
            configs.add(new ExcelExportConfig("销售订单号", "soNo", 120));
            configs.add(new ExcelExportConfig("销售订单行号", "soItem", 120));
            configs.add(new ExcelExportConfig("单位", "unit", 120));
            configs.add(new ExcelExportConfig("库存性质", "invAttr", 120));
            configs.add(new ExcelExportConfig("备注", "comments", 120));
            configs.add(new ExcelExportConfig("货主", "customerName", 120));


            workbook = HttpExcel.newListToExcel(datas, configs);
            String userAgent = request.getHeader("USER-AGENT");
            String fileName = "库存报表";
            if (userAgent.contains("Mozilla")) {
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "utf8");
            }
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;fileName=" + fileName + ".xlsx");
            response.flushBuffer();
            out = response.getOutputStream();
            workbook.write(out);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
            if(workbook != null) {
                workbook.close();
            }
        }
    }

    //导出SN列表【新】
    public void exportGoodsNew(SearchInvRequest dto,
                          HttpServletRequest request, HttpServletResponse response) throws Exception {

        ServletOutputStream out = null;
        XSSFWorkbook workbook = null;
        try {

            List<InvLocGoodsListResponse> datas = goodsMapper.selectByInvLoc(dto);
            for (InvLocGoodsListResponse data : datas) {
                if (data.getStatus()!=null){
                    GoodsStatusEnum goodsStatusEnum = GoodsStatusEnum.getEnumByCode(data.getStatus());
                    if (goodsStatusEnum!=null){
                        data.setStatusStr(goodsStatusEnum.getEnumName());
                    }
                }
            }

            List<ExcelExportConfig> configs = new ArrayList<>();
            configs.add(new ExcelExportConfig("sn码", "goodsSn", 120));
            configs.add(new ExcelExportConfig("卡板号", "pkgSn", 120));
            configs.add(new ExcelExportConfig("状态", "statusStr", 120));
            configs.add(new ExcelExportConfig("订单号", "poNo", 120));
            configs.add(new ExcelExportConfig("物料编码", "skuCode", 120));
            configs.add(new ExcelExportConfig("销售订单", "soNo", 120));
            configs.add(new ExcelExportConfig("销售订单行号", "soItem", 120));


            workbook = HttpExcel.newListToExcel(datas, configs);
            String userAgent = request.getHeader("USER-AGENT");
            String fileName = "库存SN详情";
            if (userAgent.contains("Mozilla")) {
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "utf8");
            }
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;fileName=" + fileName + ".xlsx");
            response.flushBuffer();
            out = response.getOutputStream();
            workbook.write(out);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
            if(workbook != null) {
                workbook.close();
            }
        }
    }


    //设置查询条件
    private void setInvLocSearch(SearchInvRequest dto,Goods goods){
        dto.setOwnerId(goods.getOwner());
        dto.setSkuId(goods.getSkuId());
        dto.setFactory(goods.getFactory());
        dto.setVendorId(goods.getVendorId());
        dto.setLotno(goods.getLotno());
        dto.setInvAttr(goods.getInvAttr());
        dto.setQaStatus(goods.getQaStatus());
        dto.setWhsId(goods.getWhsId());
        dto.setLocId(goods.getLocId());
        dto.setUnit(goods.getUnit());
    }


}